import random
from datetime import datetime
from compements.tool import calculate_age

# 体重获取优先级体检-档案-门诊
def select_weight_data(new_sf_date, mz_data, tj_data, mb_data):
    selected_data = None
    from_mz = False  # 标志位，表示数据是否来自门诊
    new_sf_date_dt = datetime.strptime(new_sf_date, '%Y-%m-%d')

    # 1. 优先选择同月的体检数据
    tj_date = tj_data.get('体检日期')
    if tj_date:
        tj_date_dt = datetime.strptime(tj_date, '%Y-%m-%d')
        if tj_date_dt.year == new_sf_date_dt.year and tj_date_dt.month == new_sf_date_dt.month:
            selected_data = tj_data.get('体重')
            if selected_data is not None and selected_data != "" and selected_data != "未查" and selected_data != "不详":
                from_mz = False

    # 2. 如果没有，选择档案数据
    if selected_data is None or selected_data == "" or selected_data == "未查" or selected_data == "不详":
        selected_data = mb_data.get('体重')
        from_mz = False

    # 3. 如果还没有，选择门诊数据
    if (selected_data is None or selected_data == "" or selected_data == "未查" or selected_data == "不详"):
        for mz in mz_data:
            if mz.get('随访日期:') == new_sf_date:
                selected_data = mz.get('体重')
                if selected_data is not None and selected_data != "" and selected_data != "未查" and selected_data != "不详":
                    from_mz = True  # 数据来自门诊
                    break

    return selected_data, from_mz



# 身高获取优先级体检-档案-门诊
def select_height_data(new_sf_date, mz_data, tj_data, mb_data):
    selected_data = None
    from_mz = False  # 标志位，表示数据是否来自门诊
    new_sf_date_dt = datetime.strptime(new_sf_date, '%Y-%m-%d')

    # 1. 优先选择同月的体检数据
    tj_date = tj_data.get('体检日期')
    if tj_date:
        tj_date_dt = datetime.strptime(tj_date, '%Y-%m-%d')
        if tj_date_dt.year == new_sf_date_dt.year and tj_date_dt.month == new_sf_date_dt.month:
            selected_data = tj_data.get('身高')
            if selected_data is not None and selected_data != "" and selected_data != "未查" and selected_data != "不详":
                # 数据来自体检，标记为非门诊来源
                from_mz = False

    # 2. 如果没有，选择档案数据
    if selected_data is None or selected_data == "" or selected_data == "未查" or selected_data == "不详":
        selected_data = mb_data.get('身高')
        from_mz = False

    # 3. 如果还没有，选择门诊数据
    if (selected_data is None or selected_data == "" or selected_data == "未查" or selected_data == "不详"):
        for mz in mz_data:
            if mz.get('随访日期:') == new_sf_date:
                selected_data = mz.get('身高')
                if selected_data is not None and selected_data != "" and selected_data != "未查" and selected_data != "不详":
                    from_mz = True  # 数据来自门诊
                    break

    return selected_data, from_mz



# 函数：根据不同优先级选择数据
def select_data_for_field(field_name, new_sf_date, mz_data, tj_data, mb_data):



    selected_data = None
    from_mz = False  # 标志位，表示数据是否来自门诊
    new_sf_date_dt = datetime.strptime(new_sf_date, '%Y-%m-%d')

    # 1. 优先选择与新建的随访日期一致的门诊数据
    for mz in mz_data:
        if mz.get('随访日期:') == new_sf_date:  # 使用get避免KeyError
            selected_data = mz.get(field_name)  # 使用get避免KeyError
            if selected_data is not None and selected_data != "" and selected_data != "未查" \
                    and selected_data != "不详":
                from_mz = True  # 数据来自门诊
                break

    # 2. 如果没有，选择同月的体检数据
    if not from_mz and (selected_data is None or selected_data == "" or selected_data == "未查"
                        and selected_data != "不详"):
        tj_date = tj_data.get('体检日期')  # 使用get避免KeyError
        if tj_date:
            tj_date_dt = datetime.strptime(tj_date, '%Y-%m-%d')
            if tj_date_dt.year == new_sf_date_dt.year and tj_date_dt.month == new_sf_date_dt.month:
                selected_data = tj_data.get(field_name)  # 使用get避免KeyError

    # 3. 如果没有符合条件的门诊数据和体检数据，选择档案数据
    if not from_mz and (selected_data is None or selected_data == "" or selected_data == "未查"
                        and selected_data != "不详"):
        selected_data = mb_data.get(field_name)  # 使用get避免KeyError

    return selected_data, from_mz  # 返回数据和标志位


def get_new_sf_data(mb_data, mz_data, tj_data, n_sf_time, sf_data, sfzh):
    # 根据规则为每个字段选择数据
    selected_data = {"随访日期": n_sf_time}

    # 症状其他句子处理

    # 从随访数据中提取所有已使用的句子
    used_sentences = {visit_data['症状其他'] for visit_data in sf_data.values()}

    # 高血压字典处理
    hypertension_sentences = {
        1: "患者无头晕、视物模糊等不适，按时服药，未出现药物不良反应，血压稳定，饮食作息有规律。",
        2: "患者无耳鸣、视物模糊等症状，定期服药，无药物副作用，血压稳定，生活起居规律。",
        3: "患者无头痛、眩晕等不适，服药规律，无药物过敏反应，血压保持平稳，生活作息有条不紊。",
        4: "患者无四肢乏力、胸痛等不适，按时服用降压药，未出现不良反应，血压控制理想，作息正常。",
        5: "患者无浮肿、乏力等症状，遵医嘱服药，未出现药物副作用，血压控制平稳，饮食搭配合理。",
        6: "患者无呼吸困难、咳嗽等不适，定期服药，无药物不耐受，血压保持平稳，生活起居规律。",
        7: "患者无头晕、恶心等不适，按时服用降压药，无药物副作用，血压控制在目标范围内，作息健康。",
        8: "患者无胸痛、心悸等症状，遵医嘱用药，无药物不耐受反应，血压保持良好，饮食睡眠有规律。",
        9: "患者无便秘、腹胀等不适，按时服用降压药，未出现副作用，血压维持在正常水平，饮食睡眠正常。",
        10: "患者无肢体麻木、心慌等不适，规律用药，无药物相关不适主诉，血压控制平稳，日常活动正常。",
        11: "患者无失眠、烦躁等症状，坚持服药治疗，未诉不良反应，血压管理有效，精神状态良好。",
        12: "患者无颈部僵硬、耳鸣等主诉，用药依从性好，无特殊不适，血压维持稳定，生活自理能力正常。",
        13: "患者无胸闷、气短等不适，规范进行药物治疗，耐受性良好，血压控制达标，日常活动无受限。",
        14: "患者无疲劳感、注意力不集中等症状，长期服药无异常反应，血压水平平稳，社会功能正常。",
        15: "患者无鼻出血、面部潮红等表现，持续用药无不适，血压长期稳定，生活质量保持良好。"
    }
    # 糖尿病字典处理
    diabetes_sentences = {
        1: "患者无口干、多饮等症状，遵医嘱服药，无药物副作用，血糖波动不大，饮食规律。",
        2: "患者无多饮、多尿等症状，遵医嘱服药，无药物过敏现象，血糖监测平稳，作息规律。",
        3: "患者无腹痛、腹胀等不适，按时服用降糖药，未出现副作用，血糖控制在正常范围，作息良好。",
        4: "患者无手足麻木、四肢无力等症状，服药依从性好，无药物不良反应，血糖管理较好，作息稳定。",
        5: "患者无头晕、视物模糊等症状，服药规律，无药物过敏反应，血糖水平平稳，饮食习惯良好。",
        6: "患者无恶心、呕吐等症状，服药依从性良好，无明显药物不良反应，血糖水平正常，饮食健康。",
        7: "患者无消化不良、食欲下降等不适，服药依从性良好，无药物过敏反应，血糖控制理想，饮食睡眠良好。",
        8: "患者无皮疹、瘙痒等症状，服药规律，无不良反应，血糖管理得当，饮食清淡，作息正常。",
        9: "患者无四肢乏力、胸痛等不适，按时服用降糖药，未出现不良反应，血糖保持稳定，生活规律。",
        10: "患者无晕厥、乏力等症状，按时服药，未出现药物不耐受反应，血糖保持稳定，睡眠充足。",
        11: "患者无皮肤感染、伤口不易愈合等情况，持续用药无异常，血糖控制有效，日常活动正常。",
        12: "患者无体重异常下降、多食等症状，规范治疗无不适反应，血糖监测平稳，营养状况良好。",
        13: "患者无足部麻木、刺痛等感觉异常，长期服药耐受性好，血糖水平稳定，行动能力正常。",
        14: "患者无尿频、尿急等泌尿系症状，坚持治疗未诉不良反应，血糖管理达标，生活自理良好。",
        15: "患者无视力变化、眼部不适等主诉，用药依从性高，无药物相关不适，血糖控制理想，生活质量良好。"
    }
    # 高血压合并糖尿病字典处理
    combined_sentences = {
        1: "患者无乏力、四肢麻木等不适，遵医嘱用药，无明显不良反应，血压和血糖控制稳定，睡眠质量较好。",
        2: "患者无恶心、呕吐等不适，服药依从性良好，未出现不良反应，血压和血糖控制良好，饮食习惯规律。",
        3: "患者无便秘、腹泻等症状，定期服药，无明显药物不良反应，血压和血糖保持平稳，睡眠情况正常。",
        4: "患者无头痛、眼花等不适，服药依从性高，未出现不良反应，血压和血糖保持平稳，生活作息有序。",
        5: "患者无头晕、视物模糊等不适，按时服药，未出现药物不良反应，血压和血糖保持在理想范围内，作息健康。",
        6: "患者无胸部不适、呼吸困难，服药规范，无药物不良反应，血压和血糖控制良好，睡眠状态佳。",
        7: "患者无四肢麻木、乏力等症状，按时服药，无药物副作用，血压和血糖控制在理想范围内，作息规律。",
        8: "患者无晕厥、恶心等症状，遵医嘱用药，无不良反应，血压和血糖控制较好，饮食清淡，作息正常。",
        9: "患者无头痛、眩晕等不适，服药规律，无药物不良反应，血压和血糖管理稳定，生活起居有条不紊。",
        10: "患者无乏力、头晕等症状，服药规律，无明显不良反应，血压和血糖保持在目标范围，作息健康。",
        11: "患者无心悸、多汗等不适，长期联合用药耐受性良好，血压血糖均稳定，日常活动不受限。",
        12: "患者无水肿、尿量异常等情况，规范治疗无药物副作用，血压血糖控制达标，生活自理能力正常。",
        13: "患者无皮肤感觉异常、口渴等主诉，坚持用药无不适反应，血压血糖监测平稳，精神状态良好。",
        14: "患者无胸闷、气促等症状，持续治疗未诉不良反应，血压血糖管理有效，社会功能保持正常。",
        15: "患者无失眠、焦虑等表现，双重用药依从性好，耐受性佳，血压血糖均控制理想，生活质量满意。"
    }

    # 移除已使用的句子（保留键值对结构）
    filtered_hypertension = {k: v for k, v in hypertension_sentences.items() if v not in used_sentences}
    filtered_diabetes = {k: v for k, v in diabetes_sentences.items() if v not in used_sentences}
    filtered_combined = {k: v for k, v in combined_sentences.items() if v not in used_sentences}

    print(filtered_combined, filtered_diabetes, filtered_combined)

    # 身高
    height, from_mz = select_height_data(n_sf_time, mz_data, tj_data, mb_data)
    existing_height_values = [(date, float(v['身高'])) for date, v in sf_data.items() if
                              v['身高'] is not None and v['身高'] != "未查"]
    existing_height_values.sort(key=lambda x: datetime.strptime(x[0], '%Y-%m-%d'))

    # 检查身高差距 - 只有在有历史数据时才比较
    if height is not None and existing_height_values:
        last_height = existing_height_values[-1][1]
        height_diff = abs(float(height) - last_height)
        if height_diff > 0:  # 差距大于0cm
            # 记录异常情况
            with open("./执行结果/身高体重异常记录.txt", "a+", encoding="utf-8") as f:
                f.write(
                    f"身高异常: 本次身高({height}cm)与最近一次身高({last_height}cm)差距大于0cm (差距: {height_diff:.1f}cm)\n")
                f.write(f"  最近一次随访时间: {existing_height_values[-1][0]}\n")
                f.write(f"  历史身高数据: {[(d, f'{v}cm') for d, v in existing_height_values]}\n")
                f.write(f"  数据来源: {'门诊' if from_mz else '档案/体检'}\n\n")

    selected_data["身高"] = height  # 不要再覆盖为mb_data['身高']

    # 体重
    weight, from_mz = select_weight_data(n_sf_time, mz_data, tj_data, mb_data)
    existing_weight_values = [(date, float(v['体重'])) for date, v in sf_data.items() if
                              v['体重'] is not None and v['体重'] != "未查"]
    existing_weight_values.sort(key=lambda x: datetime.strptime(x[0], '%Y-%m-%d'))
    print("根据档案、门诊、体检选出的体重:", weight)
    print("以往随访的体重:", existing_weight_values)

    # 检查体重差距 - 只有在有历史数据时才比较
    if weight is not None and existing_weight_values:
        last_weight = existing_weight_values[-1][1]
        weight_diff = abs(float(weight) - last_weight)
        if weight_diff > 10:  # 差距大于10kg
            # 记录异常情况
            with open("./执行结果/身高体重异常记录.txt", "a+", encoding="utf-8") as f:
                f.write(
                    f"体重异常: 本次体重({weight}kg)与最近一次体重({last_weight}kg)差距大于10kg (差距: {weight_diff:.1f}kg)\n")
                f.write(f"  最近一次随访时间: {existing_weight_values[-1][0]}\n")
                f.write(f"  历史体重数据: {[(d, f'{v}kg') for d, v in existing_weight_values]}\n")
                f.write(f"  数据来源: {'门诊' if from_mz else '档案/体检'}\n\n")

    if weight is not None:
        if not existing_weight_values:  # 如果是第一次随访
            change = random.choice([-3.0, -2.0, -1.0, 1.0, 2.0, 3.0])
            new_weight = float(weight) + float(change)
            new_weight = round(new_weight, 1)
        else:
            # 获取最近一次随访的体重
            last_weight = existing_weight_values[-1][1]
            print("最近一次随访的体重:", last_weight)
            # 在±2.5kg范围内随机选择变化量
            change = random.choice([-2.5, -2.0, -1.0, 1.0, 2.0, 2.5])
            new_weight = last_weight + change
            # 四舍五入到小数点后1位
            new_weight = round(new_weight, 1)
        selected_data["体重"] = new_weight
    else:
        selected_data["体重"] = weight

    # 收缩压
    sbp, from_mz = select_data_for_field('收缩压', n_sf_time, mz_data, tj_data, mb_data)
    try:
        sbp = int(float(sbp))
    except:
        sbp = random.randint(115, 138)

    existing_systolic_values = {int(v['收缩压']) for v in sf_data.values() if
                                v['收缩压'] is not None and v['收缩压'] != "未查"}
    print("根据档案、门诊、体检选出的收缩压:", sbp)
    print("以往随访的收缩压:", existing_systolic_values)

    # 如果数据不是来自门诊，才进行后续的判断和随机生成
    if not from_mz:
        # 检查收缩压是否在正常范围内(115-138)且不重复
        if sbp in existing_systolic_values or sbp > 138 or sbp < 115:
            sbp = random.randint(115, 138)
            while sbp in existing_systolic_values:
                sbp = random.randint(115, 138)
    else:
        # 数据来自门诊，但仍需检查是否在合理范围内
        if sbp > 138 or sbp < 115:
            sbp = random.randint(115, 138)

    selected_data["收缩压"] = sbp

    # 舒张压
    dbp, from_mz = select_data_for_field('舒张压', n_sf_time, mz_data, tj_data, mb_data)
    try:
        dbp = int(float(dbp))
    except:
        min_diastolic = max(65, int(float(sbp)) - 60)
        max_diastolic = min(85, int(float(sbp)))
        dbp = random.randint(min_diastolic, max_diastolic)

    existing_diastolic_values = {int(v['舒张压']) for v in sf_data.values() if
                                 v['舒张压'] is not None and v['舒张压'] != "未查"}
    print("根据档案、门诊、体检选出的舒张压:", dbp)
    print("以往随访的舒张压:", existing_diastolic_values)

    # 如果数据不是来自门诊，才进行后续的判断和随机生成
    if not from_mz:
        # 检查舒张压是否在正常范围内(60-85)且不重复
        if dbp in existing_diastolic_values or dbp > 85 or dbp < 60:
            min_diastolic = max(65, int(float(sbp)) - 60)
            max_diastolic = min(85, int(float(sbp)))
            dbp = random.randint(min_diastolic, max_diastolic)
            while dbp in existing_diastolic_values:
                dbp = random.randint(min_diastolic, max_diastolic)
    else:
        # 数据来自门诊，但仍需检查是否在合理范围内
        if dbp > 85 or dbp < 60:
            min_diastolic = max(65, int(float(sbp)) - 60)
            max_diastolic = min(85, int(float(sbp)))
            dbp = random.randint(min_diastolic, max_diastolic)

    selected_data["舒张压"] = dbp

    # 心率
    heart_rate, from_mz = select_data_for_field('心率', n_sf_time, mz_data, tj_data, mb_data)
    existing_heart_rate_values = {int(v['心率']) for v in sf_data.values() if v['心率'] != "未查"}
    print("根据档案、门诊、体检选出的心率:", heart_rate)
    print("以往随访的心率:", existing_heart_rate_values)

    # if not from_mz:  # 如果数据不是来自门诊，才进行后续的判断和随机生成
    if heart_rate is None or heart_rate in existing_heart_rate_values:
        heart_rate = random.randint(60, 99)
        while heart_rate in existing_heart_rate_values:
            heart_rate = random.randint(60, 99)
    # else:
    #     heart_rate = heart_rate  # 数据来自门诊，直接使用
    selected_data["心率"] = heart_rate

    # 腰围
    # waistline, from_mz = select_data_for_field('腰围', n_sf_time, mz_data, tj_data, mb_data)
    # # change = random.choice([-5, -4, -3, -2, -1, 1, 2, 3, 4, 5])
    # if isinstance(waistline, str):
    #     waistline = int(float(waistline))
    # # new_waistline = waistline + change
    # new_waistline = waistline
    new_waistline = mb_data['腰围']
    selected_data["腰围"] = new_waistline

    # 日吸烟量
    smoke_amount, from_mz = select_data_for_field('日吸烟量', n_sf_time, mz_data, tj_data, mb_data)
    selected_data["日吸烟量"] = smoke_amount

    # 日饮酒量
    drink_amount, from_mz = select_data_for_field('日饮酒量', n_sf_time, mz_data, tj_data, mb_data)
    selected_data["日饮酒量"] = drink_amount

    # 运动次数
    sport_times, from_mz = select_data_for_field('运动次数', n_sf_time, mz_data, tj_data, mb_data)
    selected_data["运动次数"] = sport_times

    # 运动时间
    sport_time, from_mz = select_data_for_field('运动时间', n_sf_time, mz_data, tj_data, mb_data)
    selected_data["运动时间"] = sport_time

    # 主食量
    age = calculate_age(sfzh)
    print("年龄:", age)

    food_amount, from_mz = select_data_for_field('主食量', n_sf_time, mz_data, tj_data, mb_data)
    try:
        food_amount = int(float(food_amount)) * 3
    except:
        food_amount = 300
    food_amount = int(food_amount)
    # 根据年龄调整主食量
    if age < 60:
        if food_amount > 800:
            food_amount *= 2  # 如果大于800，再乘以2
            if food_amount > 800:
                food_amount = 800  # 如果仍然大于800，设置为800
    else:
        if food_amount > 400:
            food_amount *= 2  # 如果大于400，再乘以2
            if food_amount > 400:
                food_amount = 400  # 如果仍然大于400，设置为400

    # 将最终结果存储到 selected_data
    selected_data["主食量"] = food_amount

    has_diabetes = '糖尿病' in mb_data.get('疾病史', '')
    glucose_range = (5.9, 7.0) if has_diabetes else (5.2, 6.1)# 糖尿病的血糖范围
    glucose, from_mz = select_data_for_field('空腹血糖', n_sf_time, mz_data, tj_data, mb_data)# 获取空腹血糖数据
    existing_glucose_values = {float(v['空腹血糖']) for v in sf_data.values() if v['空腹血糖'] != "未查"}

    # 先将 glucose 转换为浮点数（如果不是 None）
    if glucose is not None:
        try:
            glucose = float(glucose)
        except (ValueError, TypeError):
            glucose = None

    # 检查 glucose 是否为 None 或已经存在于 existing_glucose_values 中
    if glucose is None or glucose in existing_glucose_values or not (glucose_range[0] <= glucose <= glucose_range[1]):
        # 如果不在范围内或重复，重新生成一个不重复且在范围内的值
        glucose = round(random.uniform(*glucose_range), 1)
        while glucose in existing_glucose_values or not (glucose_range[0] <= glucose <= glucose_range[1]):
            glucose = round(random.uniform(*glucose_range), 1)
    else:
        glucose = glucose

    selected_data["空腹血糖"] = glucose

    return selected_data, filtered_hypertension, filtered_diabetes, filtered_combined
